package com.gitee.qdbp.general.common.web.controller.files;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.util.Properties;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.gitee.qdbp.able.exception.ServiceException;
import com.gitee.qdbp.able.result.ResultCode;
import com.gitee.qdbp.base.annotation.OperateRecord;
import com.gitee.qdbp.base.utils.WebTools;
import com.gitee.qdbp.general.common.api.files.service.IWebFileService;
import com.gitee.qdbp.general.common.error.FileErrorCode;
import com.gitee.qdbp.tools.files.ImageTools;
import com.gitee.qdbp.tools.files.PathTools;
import com.gitee.qdbp.tools.utils.PropertyTools;
import com.gitee.qdbp.tools.utils.StringTools;
import com.gitee.qdbp.tools.utils.VerifyTools;

/**
 * 图片处理控制器
 *
 * @author zhaohuihua
 * @version 170910
 */
@Controller
@RequestMapping("/actions/image")
public class ImageHandleController {

    @Autowired
    private IWebFileService webFileService;
    @Autowired
    @Qualifier("setting")
    private Properties setting;

    private static FileNameMap MIME_TYPES = URLConnection.getFileNameMap();

    /**
     * 图片尺寸调整<br>
     * 文件扩展名必须在allow.download.suffix配置中<br>
     * 文件必须位于文件服务配置的文件夹或allow.download.folder配置中<br>
     * 
     * @param p 文件的保存路径
     * @param w 宽度, 0表示自动计算
     * @param h 调度, 0表示自动计算
     * @throws IOException
     * @throws ServiceException
     */
    @RequestMapping("resize")
    @OperateRecord("图片尺寸调整")
    public void resize(String p, int w, int h, HttpServletResponse response) throws IOException {

        String mimeType = MIME_TYPES.getContentTypeFor(p);
        response.setContentType(mimeType);
        try {
            doResize(p, w, h, response);
        } catch (ServiceException e) {
            painError(PathTools.getExtension(p, false), w, h, e, response);
        }
    }

    private void doResize(String p, int w, int h, HttpServletResponse response) throws IOException, ServiceException {

        if (VerifyTools.isBlank(p)) {
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        // 1.获取要下载的文件的绝对路径
        String realPath = getRealPath(p);

        if (!new File(realPath).exists()) {
            throw new ServiceException(FileErrorCode.FILE_NOT_FOUND);
        }

        // 3.获取要下载的文件输入流
        try (InputStream in = new FileInputStream(realPath);) {
            // 3.1.通过response对象获取OutputStream流
            OutputStream out = response.getOutputStream();
            ImageTools.thumbnail(in, out, w, h);
        }
    }

    private void painError(String type, int w, int h, ServiceException e, HttpServletResponse response)
            throws IOException {

        if (w > 0 && h <= 0) {
            h = w;
        } else if (w <= 0 && h > 0) {
            w = h;
        } else if (w <= 0 && h <= 0) {
            w = h = 300;
        }

        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        Graphics graphics = image.getGraphics();
        graphics.setColor(new Color(0xF5, 0xF5, 0xF5));
        graphics.fillRect(0, 0, w, h);

        OutputStream out = response.getOutputStream();
        ImageIO.write(image, type, out);
    }

    // 获取文件实际保存路径, 如果是文件服务保存的, 根据文件服务配置获取文件; 否则获取WEB服务根路径下的文件
    private String getRealPath(String path) throws ServiceException {

        // 先判断文件路径是不是文件服务的路径
        String fileCenterPath = webFileService.toLocalAbsolutePath(path);
        if (fileCenterPath != null) {
            return fileCenterPath;
        }

        // WebRoot
        String serverPath = WebTools.me.getWebRoot();
        if (StringTools.isUrl(path)) {
            throw new ServiceException(ResultCode.PARAMETER_VALUE_ERROR);
        }
        if (!isAllowDownload(path, false)) {
            throw new ServiceException(ResultCode.FORBIDDEN);
        }
        return PathTools.concat(serverPath, path);
    }

    /** 判断是否允许下载 **/
    private boolean isAllowDownload(String path, boolean inFileService) {
        boolean allowSuffix = false;

        // 判断文件名后缀
        String[] suffixes = PropertyTools.getArray(setting, "allow.download.suffix");
        for (String suffix : suffixes) {
            if (path.endsWith(suffix)) {
                allowSuffix = true;
                break;
            }
        }

        // 判断文件夹
        boolean allowFolder;
        if (inFileService) {
            allowFolder = true; // 文件服务路径下的都可以下载
        } else {
            allowFolder = false;
            String[] folders = PropertyTools.getArray(setting, "allow.download.folder", false);
            if (folders == null || folders.length == 0) {
                folders = new String[] { "assets" }; // 兼容旧版本
            }
            for (String folder : folders) {
                if (path.startsWith(folder + "/") || path.startsWith("/" + folder + "/")) {
                    allowFolder = true;
                    break;
                }
            }
        }

        return allowSuffix && allowFolder;
    }
}
